package cc.rengu.igas.opms.core.service.trans.common;

import cc.rengu.igas.opms.common.constant.OpmsParamConstant;
import cc.rengu.igas.opms.common.enums.RespCodeEnum;
import cc.rengu.igas.opms.core.service.base.ManageService;
import cc.rengu.igas.opms.facade.bean.CouponInfo;
import cc.rengu.igas.opms.facade.request.EmergeDynamicQrCodeRequest;
import cc.rengu.igas.opms.facade.response.EmergeDynamicQrCodeResponse;
import cc.rengu.igas.share.core.model.UserInfo;
import cc.rengu.igas.share.core.realize.MchntService;
import cc.rengu.igas.share.core.realize.UserService;
import cc.rengu.igas.share.core.realize.impl.MchntServiceImpl;
import cc.rengu.igas.share.core.realize.impl.UserServiceImpl;
import cc.rengu.oltp.service.common.constant.AppParamConstant;
import cc.rengu.oltp.service.common.constant.TreeNodeConstant;
import cc.rengu.oltp.service.common.entity.MchntOrderInfo;
import cc.rengu.oltp.service.common.entity.SysParam;
import cc.rengu.oltp.service.common.entity.UserOrderInfo;
import cc.rengu.oltp.service.common.enums.AcctTypeEnum;
import cc.rengu.oltp.service.model.BizException;
import cc.rengu.oltp.service.model.BizResponse;
import cc.rengu.oltp.service.model.OrderInfo;
import cc.rengu.oltp.service.realize.HsmService;
import cc.rengu.oltp.service.realize.OrderService;
import cc.rengu.oltp.service.realize.SysParamService;
import cc.rengu.oltp.service.realize.impl.HsmServiceImpl;
import cc.rengu.oltp.service.realize.impl.OrderServiceImpl;
import cc.rengu.oltp.service.realize.impl.SysParamServiceImpl;
import cc.rengu.oltp.utility.util.*;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 生成动态收款码
 *
 * @author keyi
 * @modify by wangcheng
 * @date 2020/4/20.
 */
public class EmergeDynamicQrCodeService extends ManageService {
    /* 0-不支持 1-支持 第一位微信支付 第二位支付宝支付 第三位银联云闪付 第四位手机银行 */
    private String surportPayType = "0000";

    @Override
    protected Object bizBeforeCust() throws Exception {
        EmergeDynamicQrCodeRequest genDynamicQrCodeRequest = new EmergeDynamicQrCodeRequest();
        ConvertUtil.convertOutput(genDynamicQrCodeRequest);
        return genDynamicQrCodeRequest;
    }

    @Override
    protected BizResponse bizProcessCust(Object request) throws Exception {
        EmergeDynamicQrCodeRequest genDynamicQrCodeRequest = (EmergeDynamicQrCodeRequest) request;
        String instId = genDynamicQrCodeRequest.getHeader().getInstId();
        String sessionId = genDynamicQrCodeRequest.getHeader().getSession();
        String userId = genDynamicQrCodeRequest.getUserId();
        String userOrderId = genDynamicQrCodeRequest.getUserOrderId();
        CouponInfo couponInfo = genDynamicQrCodeRequest.getCouponInfo();

        //step1:判断是否上送优惠卷信息，若上送则需要校验会话标识及用户信息
        boolean isCouponTrans = null != couponInfo && !StringUtil.isEmptyOrNull(couponInfo.getDiscountId());
        if (isCouponTrans) {
            UserService userService = new UserServiceImpl();
            if (null != platMchntInfo && OpmsParamConstant.STR_ONE.equals(platMchntInfo.getGrantCreditFlag())) {
                UserInfo userInfo = userService.getUserInfo(instId, userId, sessionId);
                if (null == userInfo) {
                    rglog.error("用户未登录或者登录会话超时!");
                    throw new BizException(RespCodeEnum.USER_NOT_LOGIN_OR_SESSION_IS_EXPIRED.getRespCode(), RespCodeEnum.USER_NOT_LOGIN_OR_SESSION_IS_EXPIRED.getRespDesc());
                }
            } else {
                UserInfo userInfo = userService.getUserInfoByUserId(instId, userId);
                if (null == userInfo) {
                    rglog.error("用户信息不存在!");
                    throw new BizException(RespCodeEnum.USER_NOT_EXIT_ERROR.getRespCode(), RespCodeEnum.USER_NOT_EXIT_ERROR.getRespDesc());
                }
            }
        }

        //step2:校验订单
        OrderService orderService = new OrderServiceImpl();
        OrderInfo orderInfo = orderService.selectOrderInfoByUserOrderId(instId, userOrderId);
        if (null == orderInfo) {
            rglog.error("订单信息不存在!");
            throw new BizException(RespCodeEnum.ORDER_NOEXIT.getRespCode(), RespCodeEnum.ORDER_NOEXIT.getRespDesc());
        }
        UserOrderInfo userOrderInfo = orderInfo.getUserOrderInfo();
        List<MchntOrderInfo> mchntOrderInfoList = orderInfo.getMchntOrderInfoList();

        //step3:根据商户订单个数获取支持的支付方式(合并支付的订单只支持手机银行扫码支付)
        String qrUrl;
        if (mchntOrderInfoList.size() > OpmsParamConstant.INT_ONE) {
            rglog.info("非购买卡券商户订单个数大于1，只支持微信手机银行扫码支付.mchntOrderSize:<{}>", mchntOrderInfoList.size());
            qrUrl = mutilMachtOrderGetQrUrl(instId);
            surportPayType = "1001";
        } else {
            rglog.info("商户订单数只有一个,通过商户产品信息表获取支持的支付方式,mchntNo:<{}>", mchntOrderInfoList.get(0).getMchntNo());
            qrUrl = signleMchtnOrderGetQrUrl(instId, mchntOrderInfoList.get(0).getMchntNo());
        }

        //step4:更新二维码信息及优惠卷信息到用户订单表
        if (isCouponTrans) {
            JSONObject couponInfoJson = new JSONObject();
            couponInfoJson.put(couponInfo.getDiscountId(), couponInfo.getDiscountAmt());
            userOrderInfo.setDiscountInfo(couponInfoJson.toJSONString());
        }
        userOrderInfo.setOrderUrl(qrUrl);
        Map<String, Object> orderExntMap = new HashMap<>();
        if (!StringUtil.isEmptyOrNull(userOrderInfo.getOrderExtraInfo())) {
            orderExntMap = JSON.parseObject(userOrderInfo.getOrderExtraInfo(), Map.class);
        }
        orderExntMap.put("qrCodeType", "D");//动态码
        //增加二维码交易金额来源标识
        if (StringUtil.isEmptyOrNull(userOrderInfo.getOrderAmt()) || AmountUtil.compare(userOrderInfo.getOrderAmt(), "0") <= 0) {
            //交易金额未设置
            orderExntMap.put(OpmsParamConstant.ORDER_AMT_SOURCE, "01");
        } else {
            //交易金额已设置，支付时需要校验金额
            orderExntMap.put(OpmsParamConstant.ORDER_AMT_SOURCE, "00");
        }
        userOrderInfo.setOrderExtraInfo(JSON.toJSONString(orderExntMap));

        userOrderInfo.setUpdateTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS"));
        if (!orderService.updateOrderInfo(userOrderInfo, null, null)) {
            rglog.error("更新用户订单信息表失败");
            throw new BizException(RespCodeEnum.UPDATE_ORDER_ERROR.getRespCode(), RespCodeEnum.UPDATE_ORDER_STATUS_ERROR.getRespDesc());
        }

        EmergeDynamicQrCodeResponse genDynamicQrCodeResponse = new EmergeDynamicQrCodeResponse();
        genDynamicQrCodeResponse.setQrCode(qrUrl);
        genDynamicQrCodeResponse.setQrCodeLogoUrl("");
        genDynamicQrCodeResponse.setSurportPayType(surportPayType);
        BizResponse<EmergeDynamicQrCodeResponse> bizResponse = new BizResponse<>();
        bizResponse.setRspSysId(AppParamConstant.SYS_ID);
        bizResponse.setRespCode(RespCodeEnum.TRANS_SUCCESS.getRespCode());
        bizResponse.setRespDesc(RespCodeEnum.TRANS_SUCCESS.getRespCode());
        bizResponse.setResult(genDynamicQrCodeResponse);
        return bizResponse;
    }

    @Override
    protected void bizAfterCust(Object response) throws Exception {
        BizResponse bizResponse = (BizResponse) response;
        EmergeDynamicQrCodeResponse genDynamicQrCodeResponse = (EmergeDynamicQrCodeResponse) bizResponse.getResult();
        ConvertUtil.convertInput(genDynamicQrCodeResponse);
    }

    /**
     * 单笔商户订单获取二维码URL
     * 商户开通银联二维码:https://qr.95516.com/<acqCode>/<dynamicData>
     * 商户未开通银联二维码:银行域名+D+ 系统流水号(SM4加密)
     *
     * @param instId  机构号
     * @param mchntNo 商户号
     * @return 二维码URL
     * @throws Exception 异常
     */
    private String signleMchtnOrderGetQrUrl(String instId, String mchntNo) throws Exception {
        //获取商户支持支付产品列表
        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        String sysSeqNum = xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.SYS_SEQ_NUM);
        MchntService mchntService = new MchntServiceImpl();
        boolean checkResult = mchntService.checkMchntAuth(instId, mchntNo, null, "P01MC003", "00", AcctTypeEnum.ALL.getAcctType());
        String supportWechatPay = checkResult ? OpmsParamConstant.STR_ONE : OpmsParamConstant.STR_ZERO;
        checkResult = mchntService.checkMchntAuth(instId, mchntNo, null, "P01MC003", "01", AcctTypeEnum.ALL.getAcctType());
        String supportAlipay = checkResult ? OpmsParamConstant.STR_ONE : OpmsParamConstant.STR_ZERO;
        checkResult = mchntService.checkMchntAuth(instId, mchntNo, null, "P01MC003", "03", AcctTypeEnum.ALL.getAcctType());
        String supportMobileBankPay = checkResult ? OpmsParamConstant.STR_ONE : OpmsParamConstant.STR_ZERO;
        checkResult = mchntService.checkMchntAuth(instId, mchntNo, null, "P01PM006", "00", AcctTypeEnum.ALL.getAcctType());
        String supportCupsCloudPay = checkResult ? OpmsParamConstant.STR_ONE : OpmsParamConstant.STR_ZERO;

        surportPayType = supportWechatPay + supportAlipay + supportCupsCloudPay + supportMobileBankPay;

        /*
         * 获取当前机构是否支持银联动态码配置
         * 若当期参数没有配置或参数设置的值是不是Y 则表示法人机构不支持银联动态二维码
         */
        boolean currentInstSupDynFlag = true;
        SysParamService sysParamService = new SysParamServiceImpl();
        SysParam qrCodeTypeParams = sysParamService.getSysParamInfo(instId, OpmsParamConstant.MCHNT_PARAM_TYPE, OpmsParamConstant.INST_QRCODE_TYPE);
        if (null == qrCodeTypeParams || !AppParamConstant.YES.equals(qrCodeTypeParams.getParamStatus()) || !"CUPS".equals(qrCodeTypeParams.getParamValue())) {
            rglog.info("当前机构未配置支持银联动态码的系统参数，默认为当前机构不支持生成银联动态码");
            currentInstSupDynFlag = false;
        } else {
            //查询动态码类型设置，CUPS为银标码，IGAS为收单码
            SysParam dynamicQrCodeTypeParams = sysParamService.getSysParamInfo(instId, OpmsParamConstant.MCHNT_PARAM_TYPE, OpmsParamConstant.DYNAMIC_QRCODE_TYPE);
            if (null == dynamicQrCodeTypeParams || !AppParamConstant.YES.equals(dynamicQrCodeTypeParams.getParamStatus()) || !"CUPS".equals(dynamicQrCodeTypeParams.getParamValue())) {
                rglog.info("当前机构未配置支持银联动态码的系统参数，默认为当前机构不支持生成银联动态码");
                currentInstSupDynFlag = false;
            }
        }

        //商户支持银联云闪付的产品并且机构要支持银联动态码才允许生成动态码
        if (currentInstSupDynFlag) {
            //获取银联二维码的生成机构号
            rglog.info("商户支持银联云闪付产品，使用法人行:<{}>机构银联域名生成二维码", instId);
            SysParam sysParamInfo = sysParamService.getSysParamInfo(instId, OpmsParamConstant.MCHNT_PARAM_TYPE, OpmsParamConstant.MCHNT_QRCODE_DOMAIN_NAMEB);
            if (null == sysParamInfo || !AppParamConstant.YES.equals(sysParamInfo.getParamStatus())) {
                rglog.error("当前机构未配置银联二维码的生成订单号！instId:{}", instId);
                throw new BizException(RespCodeEnum.MCHNT_INFO_NOT_FOUND.getRespCode(), RespCodeEnum.MCHNT_INFO_NOT_FOUND.getRespDesc());
            }
            return sysParamInfo.getParamValue() + "/inf=D" + sysSeqNum;
        } else {
            rglog.info("商户不支持银联云闪付产品，使用法人行:<{}>行内域名生成二维码", instId);
            return mutilMachtOrderGetQrUrl(instId);
        }
    }

    /**
     * 多个商户订单生成二维码URL
     * 银行域名+inf=D+ 系统流水号(SM4加密)
     *
     * @param instId 机构号
     * @return 二维码URL
     */
    private String mutilMachtOrderGetQrUrl(String instId) throws Exception {
        SysParamService sysParamService = new SysParamServiceImpl();
        SysParam sysParamInfo = sysParamService.getSysParamInfo(instId, OpmsParamConstant.MCHNT_PARAM_TYPE, OpmsParamConstant.MCHNT_QRCODE_INST_DOMAIN);
        if (null == sysParamInfo) {
            rglog.info("法人行域名未配置，instId:<{}>", instId);
            throw new BizException(RespCodeEnum.SYSTEM_ERROR.getRespCode(), RespCodeEnum.SYSTEM_ERROR.getRespDesc());
        }
        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        String sysSeqNum = xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.SYS_SEQ_NUM);
        //调用加密机平台进行 国密算法加密
        return sysParamInfo.getParamValue() + "inf=D" + sysSeqNum;
    }
}
